import Flutter
import UIKit
import AVFoundation

public class BrightnessPlugin: NSObject, FlutterPlugin, FlutterStreamHandler {
    private var methodChannel: FlutterMethodChannel?
    private var eventChannel: FlutterEventChannel?
    private var eventSink: FlutterEventSink?
    private var captureSession: AVCaptureSession?
    private var sliderValue: Double = 50.0  // 默认值为50.0

    public static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterMethodChannel(name: "brightness", binaryMessenger: registrar.messenger())
        let instance = BrightnessPlugin()
        instance.methodChannel = channel
        registrar.addMethodCallDelegate(instance, channel: channel)

        let eventChannel = FlutterEventChannel(name: "brightness_event", binaryMessenger: registrar.messenger())
        eventChannel.setStreamHandler(instance)
        instance.eventChannel = eventChannel
    }

    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        if call.method == "startBrightnessStream" {
            if let arguments = call.arguments as? [String: Any],
               let sliderValue = arguments["sliderValue"] as? Double {
                self.sliderValue = sliderValue
                startCamera()
                result(nil)
            } else {
                result(FlutterError(code: "INVALID_ARGUMENTS", message: "Invalid arguments", details: nil))
            }
        } else if call.method == "setSliderValue" {
            if let arguments = call.arguments as? [String: Any],
               let newSliderValue = arguments["sliderValue"] as? Double {
                self.sliderValue = newSliderValue
                result(nil)
            } else {
                result(FlutterError(code: "INVALID_ARGUMENTS", message: "Invalid arguments", details: nil))
            }
        } else if call.method == "stopBrightnessStream" {
            stopCamera()
            result(nil)
        } else {
            result(FlutterMethodNotImplemented)
        }
    }

    public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
        self.eventSink = events
        return nil
    }

    public func onCancel(withArguments arguments: Any?) -> FlutterError? {
        self.eventSink = nil
        return nil
    }

    private func startCamera() {
        captureSession = AVCaptureSession()
        captureSession?.sessionPreset = .medium
        if let device = camera(with: .front) {
            do {
                let input = try AVCaptureDeviceInput(device: device)
                captureSession?.addInput(input)
                let output = AVCaptureVideoDataOutput()
                output.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA]
                let queue = DispatchQueue(label: "VideoQueue")
                output.setSampleBufferDelegate(self, queue: queue)
                captureSession?.addOutput(output)
                captureSession?.startRunning()
            } catch {
                print("Error opening camera: \(error)")
            }
        }
    }

    private func camera(with position: AVCaptureDevice.Position) -> AVCaptureDevice? {
        if let devices = AVCaptureDevice.devices(for: .video) as? [AVCaptureDevice] {
            return devices.first { $0.position == position }
        }
        return nil
    }

    private func stopCamera() {
        captureSession?.stopRunning()
        // 释放其他与相机相关的资源，如果有的话。
    }
}

extension BrightnessPlugin: AVCaptureVideoDataOutputSampleBufferDelegate {
    public func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        if let exifDictionary = CMGetAttachment(sampleBuffer, key: kCGImagePropertyExifDictionary, attachmentModeOut: nil) as? [String: Any],
           let N = exifDictionary["FNumber"] as? Double,
           let t = exifDictionary["ExposureTime"] as? Double,
           let ISOSpeedRatings = exifDictionary["ISOSpeedRatings"] as? [Double],
           ISOSpeedRatings.count > 0 {
            let C = 1.0
            let S = ISOSpeedRatings[0]
            var lux = (C * N * N) / (t * S)
            lux -= 0.09
            lux = max(0, lux)
            lux *= sliderValue
            DispatchQueue.main.async {
                self.eventSink?(lux)
            }
        }
    }
}
